package io.gitee.zhucan123.core.infrastructure.annotation.processor;


import com.google.auto.service.AutoService;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.Writer;
import java.util.List;
import java.util.Set;

/**
 * @author: zhuCan
 * @date: 2019/11/1 10:13
 * @description:
 */
@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("javax.persistence.Entity")
public class EntityLocalProcessor extends AbstractProcessor {

  private Filer filer;
  private Messager messager;
  private Elements elementUtils;

  @Override
  public synchronized void init(ProcessingEnvironment processingEnvironment) {
    super.init(processingEnvironment);
    filer = processingEnv.getFiler();
    messager = processingEnvironment.getMessager();
    elementUtils = processingEnvironment.getElementUtils();
  }

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    messager.printMessage(Diagnostic.Kind.NOTE, "Processor : " + getClass().getSimpleName());

    Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Entity.class);

    StringBuilder sql = new StringBuilder();

    try {
      elements.forEach(x -> {
        // 获取类上面的注解
        Entity annotation = x.getAnnotation(Entity.class);
        Table tableAnnotation = x.getAnnotation(Table.class);
        // 获取类里面的成员
        List<? extends Element> fields = x.getEnclosedElements();

        // 生成sql
        String table = annotation.name();
        sql.append("update ");
        sql.append(StringUtils.defaultIfBlank(table, tableAnnotation == null ? "" : tableAnnotation.name()));
        sql.append(" set gmt_create = DATE_ADD(gmt_create,INTERVAL -8 HOUR),gmt_modified = DATE_ADD(gmt_modified,INTERVAL -8 HOUR)");

        // 遍历类中的时间类型
        fields.forEach(filed -> {
          if (filed.getKind().isField()
              && filed.getAnnotation(Column.class) != null
              && isDate(filed.asType().toString())) {
            String column = filed.getAnnotation(Column.class).name();

            // 非创建或修改时间就增加修改此时间字段的值
            if (!isCreatedOrModified(column)){
              sql.append(", ");
              sql.append(column);
              sql.append(" = DATE_ADD(");
              sql.append(column);
              sql.append(",INTERVAL -8 HOUR)");
            }
          }
        });

        sql.append(";\n");
      });

      messager.printMessage(Diagnostic.Kind.NOTE, "sql : " + sql.toString());
      // 写入文件
      if (!elements.isEmpty()) {

        FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", "entity_local_fix.sql");
        Writer writer = resource.openWriter();
        writer.write(sql.toString());
        writer.flush();
        writer.close();

      }

    } catch (Exception e) {
      messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
    }
    return false;
  }

  /**
   * 判断是否是时间(目前只能根据toString来判断是否是时间)
   */
  private boolean isDate(String packageName) {
    return packageName.contains("Date")
        || packageName.contains("LocalDate")
        || packageName.contains("LocalDateTime");
  }

  /**
   * 判断是否是 创建或者修改时间
   *
   * @param column
   * @return
   */
  private boolean isCreatedOrModified(String column) {
    return column.contains("gmt_create") || column.contains("gmt_modified");
  }
}
